From db65e11d57fb52395a3ba2e9372bdaf29aca691c Mon Sep 17 00:00:00 2001 From: beeduck Date: Mon, 18 Jul 2016 13:10:00 -0700 Subject: Fixes for boat entities (#3265) protocol for vehicles now properly handled, protocol for boat paddles now properly handled, boats can no longer spawn underwater, boats now properly float, boat metadata now properly broadcasted. --- src/Entities/Boat.cpp | 38 ++++++++++++++++++- src/Entities/Boat.h | 23 +++++++++++- src/Entities/Entity.cpp | 22 +++++++++++ src/Entities/Entity.h | 3 ++ src/Items/ItemBoat.h | 17 ++++++++- src/Protocol/Protocol19x.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++-- src/Protocol/Protocol19x.h | 2 + 7 files changed, 186 insertions(+), 7 deletions(-) diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp index e81e57529..330e54740 100644 --- a/src/Entities/Boat.cpp +++ b/src/Entities/Boat.cpp @@ -14,7 +14,10 @@ cBoat::cBoat(double a_X, double a_Y, double a_Z) : - super(etBoat, a_X, a_Y, a_Z, 0.98, 0.7) + super(etBoat, a_X, a_Y, a_Z, 0.98, 0.7), + m_LastDamage(0), m_ForwardDirection(0), + m_DamageTaken(0.0f), m_Type(0), + m_RightPaddleUsed(false), m_LeftPaddleUsed(false) { SetMass(20.0f); SetGravity(-16.0f); @@ -37,12 +40,15 @@ void cBoat::SpawnOn(cClientHandle & a_ClientHandle) bool cBoat::DoTakeDamage(TakeDamageInfo & TDI) { + m_LastDamage = 10; if (!super::DoTakeDamage(TDI)) { return false; } - if (GetHealth() == 0) + m_World->BroadcastEntityMetadata(*this); + + if (GetHealth() <= 0) { if (TDI.Attacker != nullptr) { @@ -112,6 +118,14 @@ void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) AddSpeedY(0.2); } } + + if (GetLastDamage() > 0) + { + SetLastDamage(GetLastDamage() - 1); + } + + // Broadcast any changes in position + m_World->BroadcastEntityMetadata(*this); } @@ -130,3 +144,23 @@ void cBoat::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) AddSpeed(ToAddSpeed); } + + + + +void cBoat::SetLastDamage(int TimeSinceLastHit) +{ + m_LastDamage = TimeSinceLastHit; +} + + + + + +void cBoat::UpdatePaddles(bool a_RightPaddleUsed, bool a_LeftPaddleUsed) +{ + m_RightPaddleUsed = a_RightPaddleUsed; + m_LeftPaddleUsed = a_LeftPaddleUsed; + + m_World->BroadcastEntityMetadata(*this); +} diff --git a/src/Entities/Boat.h b/src/Entities/Boat.h index d168f5072..5815ff88c 100644 --- a/src/Entities/Boat.h +++ b/src/Entities/Boat.h @@ -31,8 +31,29 @@ public: virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override; cBoat(double a_X, double a_Y, double a_Z); -} ; + int GetLastDamage(void) const { return m_LastDamage; } + int GetForwardDirection(void) const { return m_ForwardDirection; } + + float GetDamageTaken(void) const { return m_DamageTaken; } + + int GetType(void) const { return m_Type; } + + bool IsRightPaddleUsed(void) const { return m_RightPaddleUsed; } + bool IsLeftPaddleUsed(void) const { return m_LeftPaddleUsed; } + void SetLastDamage(int TimeSinceLastHit); + void UpdatePaddles(bool rightPaddleUsed, bool leftPaddleUsed); +private: + int m_LastDamage; + int m_ForwardDirection; + + float m_DamageTaken; + + int m_Type; + + bool m_RightPaddleUsed; + bool m_LeftPaddleUsed; +} ; diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 6e1dec957..98be99a27 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -1038,6 +1038,20 @@ void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) NextSpeed -= NextSpeed * (m_AirDrag * 20.0f) * DtSec.count(); } NextSpeed.y += static_cast(fallspeed); + + // A real boat floats + if (IsBoat()) + { + // Find top water block and sit there + int NextBlockY = BlockY; + BLOCKTYPE NextBlock = NextChunk->GetBlock(RelBlockX, NextBlockY, RelBlockZ); + while (IsBlockWater(NextBlock)) + { + NextBlock = NextChunk->GetBlock(RelBlockX, ++NextBlockY, RelBlockZ); + } + NextPos.y = NextBlockY - 0.5; + NextSpeed.y = 0; + } } else { @@ -1913,6 +1927,14 @@ void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude) +cEntity * cEntity::GetAttached() +{ + return m_AttachedTo; +} + + + + void cEntity::AttachTo(cEntity * a_AttachTo) { diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index b00201f3a..6923795db 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -421,6 +421,9 @@ public: /** Updates clients of changes in the entity. */ virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = nullptr); + /** Gets entity (vehicle) attached to this entity */ + cEntity * GetAttached(); + /** Attaches to the specified entity; detaches from any previous one first */ void AttachTo(cEntity * a_AttachTo); diff --git a/src/Items/ItemBoat.h b/src/Items/ItemBoat.h index 208904130..de16c70dc 100644 --- a/src/Items/ItemBoat.h +++ b/src/Items/ItemBoat.h @@ -77,7 +77,22 @@ public: double y = Callbacks.m_Pos.y; double z = Callbacks.m_Pos.z; - cBoat * Boat = new cBoat(x + 0.5, y + 1, z + 0.5); + // Verify that block type for spawn point is water + BLOCKTYPE SpawnBlock = a_World->GetBlock(x, y, z); + if (!IsBlockWater(SpawnBlock)) + { + return false; + } + + // Block above must be air to spawn a boat (prevents spawning a boat underwater) + BLOCKTYPE BlockAbove = a_World->GetBlock(x, y + 1, z); + if (BlockAbove != E_BLOCK_AIR) + { + return false; + } + + // Spawn block at water level + cBoat * Boat = new cBoat(x + 0.5, y + 0.5, z + 0.5); Boat->Initialize(*a_World); return true; diff --git a/src/Protocol/Protocol19x.cpp b/src/Protocol/Protocol19x.cpp index 4a9732fb0..c11e05565 100644 --- a/src/Protocol/Protocol19x.cpp +++ b/src/Protocol/Protocol19x.cpp @@ -33,6 +33,7 @@ Implements the 1.9.x protocol classes: #include "../WorldStorage/FastNBT.h" #include "../WorldStorage/EnchantmentSerializer.h" +#include "../Entities/Boat.h" #include "../Entities/ExpOrb.h" #include "../Entities/Minecart.h" #include "../Entities/FallingBlock.h" @@ -2067,8 +2068,8 @@ bool cProtocol190::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) case 0x0d: HandlePacketPlayerPosLook (a_ByteBuffer); return true; case 0x0e: HandlePacketPlayerLook (a_ByteBuffer); return true; case 0x0f: HandlePacketPlayer (a_ByteBuffer); return true; - case 0x10: break; // Vehicle move - not yet implemented - case 0x11: break; // Steer boat - not yet implemented + case 0x10: HandlePacketVehicleMove (a_ByteBuffer); return true; + case 0x11: HandlePacketBoatSteer (a_ByteBuffer); return true; case 0x12: HandlePacketPlayerAbilities (a_ByteBuffer); return true; case 0x13: HandlePacketBlockDig (a_ByteBuffer); return true; case 0x14: HandlePacketEntityAction (a_ByteBuffer); return true; @@ -2318,6 +2319,29 @@ void cProtocol190::HandlePacketBlockPlace(cByteBuffer & a_ByteBuffer) +void cProtocol190::HandlePacketBoatSteer(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBool, bool, RightPaddle); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, LeftPaddle); + + // Get the players vehicle + cPlayer * Player = m_Client->GetPlayer(); + cEntity * Vehicle = Player->GetAttached(); + + if (Vehicle) + { + if (Vehicle->GetEntityType() == cEntity::etBoat) + { + auto * Boat = reinterpret_cast(Vehicle); + Boat->UpdatePaddles(RightPaddle, LeftPaddle); + } + } +} + + + + + void cProtocol190::HandlePacketChatMessage(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadVarUTF8String, AString, Message); @@ -2560,7 +2584,7 @@ void cProtocol190::HandlePacketSteerVehicle(cByteBuffer & a_ByteBuffer) } else if ((Flags & 0x1) != 0) { - // jump + // TODO: Handle vehicle jump (for animals) } else { @@ -2676,6 +2700,32 @@ void cProtocol190::HandlePacketEnchantItem(cByteBuffer & a_ByteBuffer) +void cProtocol190::HandlePacketVehicleMove(cByteBuffer & a_ByteBuffer) +{ + // This handles updating the vehicles location server side + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, xPos); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, yPos); + HANDLE_READ(a_ByteBuffer, ReadBEDouble, double, zPos); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, yaw); + HANDLE_READ(a_ByteBuffer, ReadBEFloat, float, pitch); + + // Get the players vehicle + cEntity * Vehicle = m_Client->GetPlayer()->GetAttached(); + + if (Vehicle) + { + Vehicle->SetPosX(xPos); + Vehicle->SetPosY(yPos); + Vehicle->SetPosZ(zPos); + Vehicle->SetYaw(yaw); + Vehicle->SetPitch(pitch); + } +} + + + + + void cProtocol190::HandlePacketWindowClick(cByteBuffer & a_ByteBuffer) { HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); @@ -3579,6 +3629,37 @@ void cProtocol190::WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_En break; } + case cEntity::etBoat: + { + auto & Boat = reinterpret_cast(a_Entity); + + a_Pkt.WriteBEInt8(5); // Index 6: Time since last hit + a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteBEInt32(Boat.GetLastDamage()); + + a_Pkt.WriteBEInt8(6); // Index 7: Forward direction + a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteBEInt32(Boat.GetForwardDirection()); + + a_Pkt.WriteBEInt8(7); // Index 8: Damage taken + a_Pkt.WriteBEInt8(METADATA_TYPE_FLOAT); + a_Pkt.WriteBEFloat(Boat.GetDamageTaken()); + + a_Pkt.WriteBEInt8(8); // Index 9: Type + a_Pkt.WriteBEInt8(METADATA_TYPE_VARINT); + a_Pkt.WriteBEInt32(Boat.GetType()); + + a_Pkt.WriteBEInt8(9); // Index 10: Right paddle turning + a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Boat.IsRightPaddleUsed()); + + a_Pkt.WriteBEInt8(10); // Index 11: Left paddle turning + a_Pkt.WriteBEInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Boat.IsLeftPaddleUsed()); + + break; + } // case etBoat + case cEntity::etItemFrame: { auto & Frame = reinterpret_cast(a_Entity); @@ -3777,6 +3858,7 @@ void cProtocol190::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mob) a_Pkt.WriteBEUInt8(12); // Index 12: Is saddled a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); a_Pkt.WriteBool(Pig.IsSaddled()); + break; } // case mtPig diff --git a/src/Protocol/Protocol19x.h b/src/Protocol/Protocol19x.h index e40e3aac2..d23653702 100644 --- a/src/Protocol/Protocol19x.h +++ b/src/Protocol/Protocol19x.h @@ -208,6 +208,7 @@ protected: void HandlePacketAnimation (cByteBuffer & a_ByteBuffer); void HandlePacketBlockDig (cByteBuffer & a_ByteBuffer); void HandlePacketBlockPlace (cByteBuffer & a_ByteBuffer); + void HandlePacketBoatSteer (cByteBuffer & a_ByteBuffer); void HandlePacketChatMessage (cByteBuffer & a_ByteBuffer); void HandlePacketClientSettings (cByteBuffer & a_ByteBuffer); void HandlePacketClientStatus (cByteBuffer & a_ByteBuffer); @@ -228,6 +229,7 @@ protected: void HandlePacketUseEntity (cByteBuffer & a_ByteBuffer); void HandlePacketUseItem (cByteBuffer & a_ByteBuffer); void HandlePacketEnchantItem (cByteBuffer & a_ByteBuffer); + void HandlePacketVehicleMove (cByteBuffer & a_ByteBuffer); void HandlePacketWindowClick (cByteBuffer & a_ByteBuffer); void HandlePacketWindowClose (cByteBuffer & a_ByteBuffer); -- cgit v1.2.3